var Cesium = require("cesium/Cesium");
/****
 *cesium 绘制工具类
 ****/
var CesiumDrawHelper = function(viewer) {
  this.viewer = viewer;
  this.camera = viewer.camera;
  this.scene = viewer.scene;
  this.globe = viewer.scene.globe;
  this.canvas = viewer.scene.canvas;
  this.drawEntities = []; //绘制完成的点线面等要素，用来清除
  this.movehandler = null; //鼠标移动handler
  this.opeHandler = null; //鼠标左键、右键单击handler
  this.mousePosition = null;
  this.animateFrame = -1;
  this.mouseTips = null;
  this.currentCoord = [0, 0, 0]; //鼠标当前位置经纬度高度
  this.cartesian3Coord = null; //鼠标当前位置Cartesian3坐标
  this.currentDrawEntity = null; //正在绘制时的点线面对象
  this.measureUtil = null; //测量工具类
  this._init();
};
CesiumDrawHelper.prototype = {
  constructor: CesiumDrawHelper,
  _init: function() {
    var self = this;
    this.measureUtil = new CesiumMeasureUtil(this.viewer, this.drawEntities);
    this.movehandler = new Cesium.ScreenSpaceEventHandler(this.canvas);
    this.movehandler.setInputAction(function(movement) {
      self.mousePosition = movement;
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    this.mouseTips = document.createElement("div");
    this.mouseTips.setAttribute("id", "cesiumMouseTips");
    this.mouseTips.style["position"] = "fixed";
    this.mouseTips.style["padding"] = "2px 5px";
    this.mouseTips.style["font-size"] = "12px";
    this.mouseTips.style["color"] = "#fff";
    this.mouseTips.style["display"] = "none";
    this.mouseTips.style["max-width"] = "150px";
    // this.mouseTips.style["line-height"]='20px';
    this.mouseTips.style["border-radius"] = "4px";
    this.mouseTips.style["background-color"] = "rgba(0,0,0,.5)";
    this.mouseTips.style["pointer-events"] = "none";
    this.mouseTips.style["z-index"] = 100;
    document.body.appendChild(this.mouseTips);
  },
  clearOnlyEntiry: function() {
    var entities = this.viewer.entities;
    for (i = 0; i < this.drawEntities.length; i++) {
      entities.remove(this.drawEntities[i]);
    }
    this.drawEntities = [];
  },
  clear: function() {
    var entities = this.viewer.entities;
    for (i = 0; i < this.drawEntities.length; i++) {
      entities.remove(this.drawEntities[i]);
    }
    this.drawEntities = [];
    this._clearEffect();
    this.measureUtil.clear();
    this._closeRequestAnimationFrame();
    if (this.movehandler) {
      this.movehandler.destroy();
      this.movehandler = null;
    }
  },
  setDepthTestAgainstTerrain: function(bool) {
    viewer.scene.globe.depthTestAgainstTerrain = bool;
    viewer.scene.globe.depthTestAgainstTerrain = false;
  },
  //开启requestAnimationFrame方法，替代MOUSE_MOVE事件，可以提升效率
  _requestAnimationFrame: function(callback) {
    var self = this;
    var then = Date.now();
    var frametime = 50; //间隔多长时间刷新（单位毫秒）
    (function mousemove() {
      self.animateFrame = requestAnimationFrame(mousemove);
      var now = Date.now();
      var delta = now - then;
      if (delta > frametime) {
        then = now - (delta % frametime);
        if (!self.mousePosition) {
          return;
        }
        if (
          self.mousePosition.endPosition.x <= 160 ||
          self.mousePosition.endPosition.y <= 0
        ) {
          self.mouseTips.style["display"] = "none";
          return;
        }
        // self.mouseTips.innerHTML = "点击球面添加点,右键单击结束绘制";
        // self.mouseTips.style["left"]=(self.mousePosition.endPosition.x + 15) + "px";
        // self.mouseTips.style["top"]=(self.mousePosition.endPosition.y + 70) + "px";
        // self.mouseTips.style["display"]='block';

        var lon = null,
          lat = null,
          height = null;

        /***
         **cesium原生方式鼠标点位获取方式--------------------开始
         ***/
        //地形和模型拾取结合判断，如果不是在模型(倾斜摄影、模型、entity等)上拾取，就是在地形上拾取
        var ray = self.camera.getPickRay(self.mousePosition.endPosition);
        var pos = self.globe.pick(ray, self.scene);
        var feature = self.scene.pick(self.mousePosition.endPosition);
        //如果是在倾斜摄影或模型上拾取
        // if(feature){
        if (
          feature &&
          (feature.primitive instanceof Cesium.Cesium3DTileset ||
            feature.primitive instanceof Cesium.Model)
        ) {
          // console.log(feature);
          // console.log(feature.primitive instanceof Cesium.Cesium3DTileFeature);
          //这个操作的目的是当鼠标移入绘制的点上时出现bug
          let cartesian = self.scene.pickPosition(
            self.mousePosition.endPosition
          );
          if (Cesium.defined(cartesian)) {
            self.cartesian3Coord = cartesian;
            let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
            lon = parseFloat(
              Cesium.Math.toDegrees(cartographic.longitude).toFixed(6)
            );
            lat = parseFloat(
              Cesium.Math.toDegrees(cartographic.latitude).toFixed(6)
            );
            height = parseFloat(cartographic.height.toFixed(2));
            // var height2 = viewer.scene.sampleHeight(cartographic);
            // console.log(height,height2);
            if (height) {
              height = parseFloat(height.toFixed(2));
            }
          }
        } else {
          //地形上拾取
          if (Cesium.defined(pos)) {
            self.cartesian3Coord = pos;
            let cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic(
              pos
            );
            //将弧度转为度的十进制度表示
            lon = parseFloat(
              Cesium.Math.toDegrees(cartographic.longitude).toFixed(6)
            );
            lat = parseFloat(
              Cesium.Math.toDegrees(cartographic.latitude).toFixed(6)
            );
            height = parseFloat(self.globe.getHeight(cartographic).toFixed(6));
          }
        }
        /***
         **cesium原生方式鼠标点位获取方式--------------------结束
         ***/

        /***
         **超图鼠标点位获取方式--------------------开始
         ***/
        // let cartesian2 = viewer.scene.pickPosition(self.mousePosition.endPosition);
        // if (Cesium.defined(cartesian2) ){
        //     let cartographic2 = Cesium.Cartographic.fromCartesian(cartesian2);
        //     lon = parseFloat(Cesium.Math.toDegrees(cartographic2.longitude).toFixed(6));
        //     lat = parseFloat(Cesium.Math.toDegrees(cartographic2.latitude).toFixed(6));
        //     height = parseFloat(cartographic2.height.toFixed(2));
        //     if(!height){
        //         height = 0;
        //     }
        // }
        /***
         **超图鼠标点位获取方式--------------------结束
         ***/
        self.currentCoord = [lon, lat, height];
        //执行回调
        callback();
      }
    })();
  },
  //取消requestAnimationFrame事件
  _closeRequestAnimationFrame: function() {
    window.cancelAnimationFrame(this.animateFrame);
  },
  //清除操作
  _clearEffect: function() {
    if (this.opeHandler) {
      this.opeHandler.destroy();
      this.opeHandler = null;
    }
    this.currentDrawEntity = null;
    this.mouseTips.style["display"] = "none";
    this.scene.postProcessStages.fxaa.enabled = false;
  },
  //handler监听左键、右键点击
  _createHandler: function(leftcallback, rightcallback) {
    this.opeHandler = new Cesium.ScreenSpaceEventHandler(this.canvas);
    this.opeHandler.setInputAction(function(click) {
      leftcallback(click);
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    this.opeHandler.setInputAction(function(click) {
      rightcallback(click);
    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  },
  _drawPoint: function(point, config) {
    var entity = this.viewer.entities.add({
      name: "点几何对象",
      position: Cesium.Cartesian3.fromDegrees(point[0], point[1], point[2]),
      label: {
        text: config.name,
        font: "12px sans-serif", //字体样式
        fillColor: Cesium.Color.WHITE, //字体颜色
        pixelOffset: new Cesium.Cartesian2(10, 0),
        backgroundColor: Cesium.Color.AQUA, //背景颜色
        showBackground: false, //是否显示背景颜色
        style: Cesium.LabelStyle.FILL, //label样式
        outlineWidth: 0,
        verticalOrigin: Cesium.VerticalOrigin.CENTER, //垂直位置
        horizontalOrigin: Cesium.HorizontalOrigin.LEFT, //水平位置
        disableDepthTestDistance: config.disableDepthTestDistance
      },
      point: {
        color: Cesium.Color.fromCssColorString(config.color),
        pixelSize: config.size,
        // outlineColor: Cesium.Color.WHITE,
        outlineColor: Cesium.Color.fromCssColorString(config.outlineColor),
        outlineWidth: config.outlineWidth,
        // disableDepthTestDistance: Number.POSITIVE_INFINITY
        disableDepthTestDistance: config.disableDepthTestDistance,
        heightReference: config.clampToGround
      }
    });
    this.drawEntities.push(entity);
    return entity;
  },
  _drawPolyline: function(positions, config) {
    var entity = viewer.entities.add({
      polyline: {
        positions: positions,
        width: config.lineWidth,
        // material: new Cesium.PolylineGlowMaterialProperty({
        //     color: Cesium.Color.CHARTREUSE.withAlpha(.2)
        // }),
        material: Cesium.Color.fromCssColorString(config.color).withAlpha(0.9),
        //这个属性对Cesium.CallbackProperty动态传值的方式不起作用，直接点数组传入的是可以的
        depthFailMaterial: Cesium.Color.fromCssColorString(
          config.color
        ).withAlpha(0.5),
        clampToGround: config.lineclampToGround
      }
    });
    this.drawEntities.push(entity);
    return entity;
  },
  //这个函数跟_drawPolyline区别就是，不存储在drawEntities中，绘制完后删除，在根据起止点进行重新生成，主要是解决高度测量线看不见的问题
  _drawPolylineBydepthFail: function(positions, config) {
    var entity = viewer.entities.add({
      polyline: {
        positions: positions,
        width: config.lineWidth,
        // material: new Cesium.PolylineGlowMaterialProperty({
        //     color: Cesium.Color.CHARTREUSE.withAlpha(.2)
        // }),
        material: Cesium.Color.fromCssColorString(config.color).withAlpha(0.9),
        //这个属性对Cesium.CallbackProperty动态传值的方式不起作用，直接点数组传入的是可以的
        depthFailMaterial: Cesium.Color.fromCssColorString(
          config.color
        ).withAlpha(0.5),
        clampToGround: config.lineclampToGround
      }
    });
    return entity;
  },
  _drawPolygon: function(points, config) {
    var entity = this.viewer.entities.add({
      polygon: {
        // extrudedHeight:8,
        perPositionHeight: config.perPositionHeight, //如果不加这个属性，则面总是会贴地
        hierarchy: points,
        material: Cesium.Color.fromCssColorString(config.color).withAlpha(0.5)
      }
    });
    this.drawEntities.push(entity);
    return entity;
  },
  drawPoint: function(cfg, callback) {
    //配置对象合并
    var config = {
      name: "",
      color: "#ffa500",
      size: 6,
      outlineColor: "#ffa500",
      outlineWidth: 0,
      clampToGround: Cesium.HeightReference.NONE,
      disableDepthTestDistance: 0
    };
    if (cfg) {
      Object.assign(config, cfg);
    }
    var drawptArray = [],
      ptentities = [];
    this.setDepthTestAgainstTerrain(true);
    var self = this;
    this._closeRequestAnimationFrame();
    this._requestAnimationFrame(function() {});
    this._clearEffect();
    this._createHandler(
      function(click) {
        var ray = self.camera.getPickRay(click.position);
        var pos = self.globe.pick(ray, self.scene);
        var feature = self.scene.pick(click.position);
        if (feature) {
          if (feature.primitive instanceof Cesium.PointPrimitive) {
            return;
          }
        }
        if (pos || feature) {
          var pt = [
            self.currentCoord[0],
            self.currentCoord[1],
            self.currentCoord[2]
          ];
          var ent = self._drawPoint(pt, config);
          ptentities.push(ent);
          drawptArray.push(pt);
        }
      },
      function() {
        self._clearEffect();
        self._closeRequestAnimationFrame();
        if (callback) {
          callback(drawptArray, ptentities);
        }
      }
    );
  },
  //只绘制一个点
  drawSinglePoint: function(cfg, callback) {
    //配置对象合并
    var config = {
      name: "",
      color: "#ffa500",
      size: 8,
      outlineColor: "#ffffff",
      outlineWidth: 2,
      clampToGround: Cesium.HeightReference.NONE,
      disableDepthTestDistance: Number.POSITIVE_INFINITY
    };
    if (cfg) {
      Object.assign(config, cfg);
    }
    // this.setDepthTestAgainstTerrain(true);
    var self = this;
    this._closeRequestAnimationFrame();
    this._requestAnimationFrame(function() {});
    this._clearEffect();
    this._createHandler(
      click => {
        var ray = self.camera.getPickRay(click.position);
        var pos = self.globe.pick(ray, self.scene);
        var feature = self.scene.pick(click.position);
        if (feature) {
          if (feature.primitive instanceof Cesium.PointPrimitive) {
            return;
          }
        }
        if (pos || feature) {
          var pt = [
            self.currentCoord[0],
            self.currentCoord[1],
            self.currentCoord[2]
          ];
          var et = self._drawPoint(pt, config);

          self._clearEffect();
          self._closeRequestAnimationFrame();
          if (callback) {
            callback(self.currentCoord, this.viewer.entities.getById(et.id));
          }
        }
      },
      () => {
        self._clearEffect();
        self._closeRequestAnimationFrame();
      }
    );
  },
  addLabel: function(point, cfg) {
    //配置对象合并
    var config = {
      name: "写字楼",
      disableDepthTestDistance: Number.POSITIVE_INFINITY
    };
    if (cfg) {
      Object.assign(config, cfg);
    }
    var entity = this.viewer.entities.add({
      name: "",
      position: Cesium.Cartesian3.fromDegrees(point[0], point[1], point[2]),
      label: {
        text: config.name,
        font: "12px sans-serif", //字体样式
        fillColor: Cesium.Color.YELLOW, //字体颜色
        pixelOffset: new Cesium.Cartesian2(10, 0),
        backgroundColor: Cesium.Color.AQUA, //背景颜色
        showBackground: false, //是否显示背景颜色
        style: Cesium.LabelStyle.FILL, //label样式
        outlineWidth: 0,
        verticalOrigin: Cesium.VerticalOrigin.CENTER, //垂直位置
        horizontalOrigin: Cesium.HorizontalOrigin.LEFT, //水平位置
        disableDepthTestDistance: config.disableDepthTestDistance
      }
    });
    this.drawEntities.push(entity);
    return entity;
  },
  addImageLabel: function(point, cfg) {
    //配置对象合并
    var config = {
      id: null,
      name: "",
      image: "images/poi/jingqu.png",
      width: 36,
      height: 36,
      xoffset: 0,
      yoffset: 0,
      show: true,
      distanceDisplayCondition: 1000000,
      clampToGround: Cesium.HeightReference.NONE,
      disableDepthTestDistance: Number.POSITIVE_INFINITY,
      angle: 0
    };
    if (cfg) {
      Object.assign(config, cfg);
    }
    var entity = this.viewer.entities.add({
      id: config.id,
      name: config.name,
      position: Cesium.Cartesian3.fromDegrees(point[0], point[1], point[2]),
      show: config.show,
      //     label: {
      //         text: config.name,
      //         font: '12px sans-serif',    //字体样式
      //         fillColor:Cesium.Color.WHITE,        //字体颜色
      //         pixelOffset:new Cesium.Cartesian2(10, 0),
      //         backgroundColor:Cesium.Color.AQUA,    //背景颜色
      //         showBackground:false,                //是否显示背景颜色
      //         style: Cesium.LabelStyle.FILL,        //label样式
      //         outlineWidth : 0,
      //         verticalOrigin : Cesium.VerticalOrigin.CENTER,//垂直位置
      //         horizontalOrigin :Cesium.HorizontalOrigin.LEFT,//水平位置
      //         disableDepthTestDistance: config.disableDepthTestDistance,
      //     },
      billboard: {
        pixelOffset: new Cesium.Cartesian2(config.xoffset, config.yoffset),
        image: config.image,
        width: config.width,
        height: config.height,
        rotation: config.angle,
        distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
          0,
          config.distanceDisplayCondition
        ),
        disableDepthTestDistance: config.disableDepthTestDistance,
        heightReference: config.clampToGround
      }
    });
    this.drawEntities.push(entity);
    return entity;
  },
  //文本标注
  drawLabel: function(cfg, callback) {
    //配置对象合并
    var config = {
      name: "写字楼",
      disableDepthTestDistance: Number.POSITIVE_INFINITY
    };
    if (cfg) {
      Object.assign(config, cfg);
    }
    // this.setDepthTestAgainstTerrain(true);
    var self = this;
    this._closeRequestAnimationFrame();
    this._requestAnimationFrame(function() {});
    this._clearEffect();
    this._createHandler(
      function(click) {
        var ray = self.camera.getPickRay(click.position);
        var pos = self.globe.pick(ray, self.scene);
        var feature = self.scene.pick(click.position);
        if (feature) {
          if (feature.primitive instanceof Cesium.PointPrimitive) {
            return;
          }
        }
        if (pos || feature) {
          var pt = [
            self.currentCoord[0],
            self.currentCoord[1],
            self.currentCoord[2]
          ];
          self.addLabel(pt, config);
        }
      },
      function() {
        self._clearEffect();
        self._closeRequestAnimationFrame();
        if (callback) {
          callback(
            drawptArray,
            viewer.entities.getById(self.currentDrawEntity.id)
          );
        }
      }
    );
  },
  //图片标注
  drawImage: function(cfg, callback) {
    //配置对象合并
    var config = {
      name: "",
      image: "images/poi/jingqu.png",
      width: 36,
      height: 36,
      clampToGround: Cesium.HeightReference.NONE,
      disableDepthTestDistance: Number.POSITIVE_INFINITY
    };
    if (cfg) {
      Object.assign(config, cfg);
    }
    // this.setDepthTestAgainstTerrain(true);
    var self = this;
    this._closeRequestAnimationFrame();
    this._requestAnimationFrame(function() {});
    this._clearEffect();
    this._createHandler(
      function(click) {
        var ray = self.camera.getPickRay(click.position);
        var pos = self.globe.pick(ray, self.scene);
        var feature = self.scene.pick(click.position);
        if (feature) {
          if (feature.primitive instanceof Cesium.PointPrimitive) {
            return;
          }
        }
        if (pos || feature) {
          var pt = [
            self.currentCoord[0],
            self.currentCoord[1],
            self.currentCoord[2]
          ];
          self.addImageLabel(pt, config);
        }
      },
      function() {
        self._clearEffect();
        self._closeRequestAnimationFrame();
        if (callback) {
          callback(
            drawptArray,
            viewer.entities.getById(self.currentDrawEntity.id)
          );
        }
      }
    );
  },
  //ismeasure：是否测量距离，groundMeasure：是否贴地距离
  drawPolyline: function(cfg, callback) {
    //配置对象合并
    var config = {
      //公共配置
      ismeasure: false,
      groundMeasure: false,
      name: "",
      color: "#ffa500",
      //点配置
      size: 6,
      outlineColor: "#ffa500",
      outlineWidth: 0,
      clampToGround: Cesium.HeightReference.NONE,
      disableDepthTestDistance: 0,
      //线配置
      lineWidth: 2,
      lineclampToGround: false
    };
    if (cfg) {
      Object.assign(config, cfg);
    }
    this.setDepthTestAgainstTerrain(true);
    var self = this;
    var drawptArray = []; //绘制的所有点
    var linesumlength = 0; //线总长度
    var segmentlength = 0; //当前动态绘制线的长度
    this._closeRequestAnimationFrame();
    this._requestAnimationFrame(function() {
      var newpos = [
        self.currentCoord[0],
        self.currentCoord[1],
        self.currentCoord[2]
      ];
      drawptArray.pop();
      drawptArray.push(newpos);
      if (config.ismeasure) {
        if (drawptArray.length > 1) {
          var point1 = newpos;
          var point2 = drawptArray[drawptArray.length - 2];
          segmentlength = 0;
          if (config.groundMeasure) {
            segmentlength = self.measureUtil.getFollowDistance(
              point1[1],
              point1[0],
              point2[1],
              point2[0]
            );
          } else {
            segmentlength = self.measureUtil.getFlatternDistance(
              point1[1],
              point1[0],
              point1[2],
              point2[1],
              point2[0],
              point2[2]
            );
          }
        }
      }
    });
    this._clearEffect();
    this.scene.postProcessStages.fxaa.enabled = true;
    this._createHandler(
      function(click) {
        var ray = self.camera.getPickRay(click.position);
        var pos = self.globe.pick(ray, self.scene);
        var feature = self.scene.pick(click.position);
        if (feature) {
          if (feature.primitive instanceof Cesium.PointPrimitive) {
            return;
          }
        }
        if (pos || feature) {
          var pt = [
            self.currentCoord[0],
            self.currentCoord[1],
            self.currentCoord[2]
          ];
          drawptArray.push(pt);
          if (config.ismeasure) {
            self._drawPoint(pt, config);
          }
          var len = drawptArray.length;
          var dynamicPositions = new Cesium.CallbackProperty(function() {
            return Cesium.Cartesian3.fromDegreesArrayHeights(
              [].concat.apply([], JSON.parse(JSON.stringify(drawptArray)))
            );
          }, false);
          var totallength = new Cesium.CallbackProperty(function() {
            // return JSON.parse(JSON.stringify(drawptArray));
            return (
              "总长：" +
              (linesumlength + (segmentlength ? segmentlength : 0)).toFixed(1) +
              "米"
            );
          }, false);
          if (len > 1) {
            if (self.currentDrawEntity == null) {
              self.currentDrawEntity = self._drawPolyline(
                dynamicPositions,
                config
              );
              if (config.ismeasure) {
                self.measureUtil.totalLengthLabel(drawptArray[0], totallength);
              }
            } else {
              if (config.ismeasure) {
                var point1 = drawptArray[len - 2];
                var point2 = drawptArray[len - 3];
                var distance = 0;
                if (config.groundMeasure) {
                  distance = self.measureUtil.getFollowDistance(
                    point1[1],
                    point1[0],
                    point2[1],
                    point2[0]
                  );
                } else {
                  distance = self.measureUtil.getFlatternDistance(
                    point1[1],
                    point1[0],
                    point1[2],
                    point2[1],
                    point2[0],
                    point2[2]
                  );
                }
                distance = isNaN(distance) ? 0 : distance;
                segmentlength = 0;
                linesumlength += distance;
                self.measureUtil.segmentLabel(point1, point2, distance);
              }
            }
          }
        }
      },
      function() {
        drawptArray.pop();
        segmentlength = 0;
        self._closeRequestAnimationFrame();
        self.setDepthTestAgainstTerrain(false);
        if (callback && self.currentDrawEntity) {
          callback(
            drawptArray,
            viewer.entities.getById(self.currentDrawEntity.id)
          );
        } else {
          if (callback) {
            callback();
          }
        }
        self._clearEffect();
      }
    );
  },
  //绘制直线，只有两个端点的直线，第三个参数是实时调用方法
  drawSingleline: function(cfg, callback, realtime) {
    //配置对象合并
    var config = {
      //公共配置
      ismeasure: false,
      groundMeasure: false,
      name: "",
      color: "#ffa500",
      //点配置
      size: 6,
      outlineColor: "#ffa500",
      outlineWidth: 0,
      clampToGround: Cesium.HeightReference.NONE,
      disableDepthTestDistance: 0,
      //线配置
      lineWidth: 2,
      lineclampToGround: false
    };
    if (cfg) {
      Object.assign(config, cfg);
    }
    this.setDepthTestAgainstTerrain(true);
    var self = this;
    var drawptArray = []; //绘制的所有点
    this._closeRequestAnimationFrame();
    this._requestAnimationFrame(function() {
      var newpos = [
        self.currentCoord[0],
        self.currentCoord[1],
        self.currentCoord[2]
      ];
      drawptArray.pop();
      drawptArray.push(newpos);
      if (drawptArray.length > 1) {
        if (realtime) {
          realtime(drawptArray);
        }
      }
    });
    this._clearEffect();
    this.scene.postProcessStages.fxaa.enabled = true;
    this._createHandler(
      function(click) {
        var ray = self.camera.getPickRay(click.position);
        var pos = self.globe.pick(ray, self.scene);
        var feature = self.scene.pick(click.position);
        if (feature) {
          if (feature.primitive instanceof Cesium.PointPrimitive) {
            return;
          }
        }
        if (pos || feature) {
          var pt = [
            self.currentCoord[0],
            self.currentCoord[1],
            self.currentCoord[2]
          ];
          drawptArray.push(pt);
          var len = drawptArray.length;
          var dynamicPositions = new Cesium.CallbackProperty(function() {
            return Cesium.Cartesian3.fromDegreesArrayHeights(
              [].concat.apply([], JSON.parse(JSON.stringify(drawptArray)))
            );
          }, false);
          if (len > 1) {
            if (self.currentDrawEntity == null) {
              self.currentDrawEntity = self._drawPolyline(
                dynamicPositions,
                config
              );
            }
          }
          if (len == 3) {
            drawptArray.pop();
            self._closeRequestAnimationFrame();
            if (callback) {
              callback(
                drawptArray,
                viewer.entities.getById(self.currentDrawEntity.id)
              );
            }
            self._clearEffect();
          }
        }
      },
      function() {
        drawptArray.pop();
        self._closeRequestAnimationFrame();
        self.setDepthTestAgainstTerrain(false);
        if (callback && self.currentDrawEntity) {
          callback(
            drawptArray,
            viewer.entities.getById(self.currentDrawEntity.id)
          );
        } else {
          if (callback) {
            callback();
          }
        }
        self._clearEffect();
      }
    );
  },
  //ismeasure：是否测量面积--参数都可以不传，callback是绘制结束时的回调
  drawPolygon: function(cfg, callback) {
    //配置对象合并
    var config = {
      //公共配置
      ismeasure: false,
      name: "",
      color: "#ffa500",
      //点配置
      size: 6,
      outlineColor: "#ffa500",
      outlineWidth: 0,
      clampToGround: Cesium.HeightReference.NONE,
      disableDepthTestDistance: 0,
      //线配置
      lineWidth: 1,
      lineclampToGround: false,
      //面配置
      perPositionHeight: true,
      //计算面积时是空间面积、投影面积、还是贴地面积
      measureType: "kj"
    };
    this.setDepthTestAgainstTerrain(true);
    if (cfg) {
      Object.assign(config, cfg);
    }
    var self = this;
    var drawptArray = []; //绘制的所有点
    var sumarea = 0; //面积数值
    var labelcenterpt = null; //label中心坐标，随面动态更新
    this._closeRequestAnimationFrame();
    this._requestAnimationFrame(function() {
      var newpos = [
        self.currentCoord[0],
        self.currentCoord[1],
        self.currentCoord[2]
      ];
      drawptArray.pop();
      drawptArray.push(newpos);
      if (config.ismeasure) {
        if (drawptArray.length > 2) {
          if (config.measureType == "kj") {
            sumarea = self.measureUtil.SphericalPolygonAreaMeters(drawptArray);
          } else if (config.measureType == "ty") {
            sumarea = self.measureUtil.TyPolygonAreaMeters(drawptArray);
          } else if (config.measureType == "td") {
            sumarea = self.measureUtil.SphericalPolygonAreaMeters(drawptArray);
          }
        }
      }
    });
    this._clearEffect();
    this.scene.postProcessStages.fxaa.enabled = true;
    this._createHandler(
      function(click) {
        var ray = self.camera.getPickRay(click.position);
        var pos = self.globe.pick(ray, self.scene);
        var feature = self.scene.pick(click.position);
        if (feature) {
          if (feature.primitive instanceof Cesium.PointPrimitive) {
            return;
          }
        }
        if (pos || feature) {
          var pt = [
            self.currentCoord[0],
            self.currentCoord[1],
            self.currentCoord[2]
          ];
          drawptArray.push(pt);
          if (config.ismeasure) {
            self._drawPoint(pt, config);
          }
          var len = drawptArray.length;
          var dynamicPositions = new Cesium.CallbackProperty(function() {
            // return JSON.parse(JSON.stringify(drawptArray));
            return new Cesium.PolygonHierarchy(
              Cesium.Cartesian3.fromDegreesArrayHeights(
                [].concat.apply([], JSON.parse(JSON.stringify(drawptArray)))
              )
            );
          }, false);
          if (len == 2) {
            var linePositions = new Cesium.CallbackProperty(function() {
              return Cesium.Cartesian3.fromDegreesArrayHeights(
                [].concat.apply([], JSON.parse(JSON.stringify(drawptArray)))
              );
            }, false);
            self._drawPolyline(linePositions, config);
          }
          if (len > 2) {
            if (self.currentDrawEntity == null) {
              self.currentDrawEntity = self._drawPolygon(
                dynamicPositions,
                config
              );
              if (config.ismeasure) {
                if (config.measureType == "kj") {
                  sumarea = self.measureUtil.SphericalPolygonAreaMeters(
                    drawptArray
                  );
                } else if (config.measureType == "ty") {
                  sumarea = self.measureUtil.TyPolygonAreaMeters(drawptArray);
                } else if (config.measureType == "td") {
                  sumarea = self.measureUtil.SphericalPolygonAreaMeters(
                    drawptArray
                  );
                }
                var totalarea = new Cesium.CallbackProperty(function() {
                  return sumarea == 0
                    ? ""
                    : "面积：" + sumarea.toFixed(1) + " 平方米";
                }, false);
                var areacenter = new Cesium.CallbackProperty(function() {
                  var polyPositions = new Cesium.PolygonHierarchy(
                    Cesium.Cartesian3.fromDegreesArrayHeights(
                      [].concat.apply(
                        [],
                        JSON.parse(JSON.stringify(drawptArray))
                      )
                    )
                  );
                  labelcenterpt = Cesium.BoundingSphere.fromPoints(
                    polyPositions.positions
                  ).center;
                  return labelcenterpt;
                }, false);
                self.measureUtil.areaLabel(areacenter, totalarea);
              }
            } else {
            }
          }
        }
      },
      function() {
        drawptArray.pop();
        if (config.ismeasure) {
          if (drawptArray.length > 2) {
            if (config.measureType == "kj") {
              sumarea = self.measureUtil.SphericalPolygonAreaMeters(
                drawptArray
              );
            } else if (config.measureType == "ty") {
              sumarea = self.measureUtil.TyPolygonAreaMeters(drawptArray);
            } else if (config.measureType == "td") {
              sumarea = self.measureUtil.TdPolygonAreaMeters(drawptArray);
              self.setDepthTestAgainstTerrain(false);
            }
          } else {
            sumarea = 0;
          }
        }
        self.setDepthTestAgainstTerrain(false);
        self._closeRequestAnimationFrame();
        if (callback && self.currentDrawEntity) {
          callback(
            drawptArray,
            viewer.entities.getById(self.currentDrawEntity.id)
          );
        } else {
          if (callback) {
            callback();
          }
        }
        self._clearEffect();
      }
    );
  },
  //空间距离（三种方式：三角面，垂直距离、水平距离）
  drawTriangle: function(type, cfg, callback) {
    //配置对象合并
    var config = {
      //公共配置
      ismeasure: false,
      groundMeasure: false,
      name: "",
      color: "#ffa500",
      //线配置
      lineWidth: 2,
      lineclampToGround: false
    };
    if (cfg) {
      Object.assign(config, cfg);
    }
    this.setDepthTestAgainstTerrain(true);
    var self = this;
    var firstPt = null, //起点
      endPt = null, //终点
      hPt = null; //根据起点和终点计算出的直角点
    var threeLinelengs = ["", "", ""]; //三角形三边长数组
    var hlineentity = null,
      vlineentity = null; //临时绘制的高度水平线
    this._closeRequestAnimationFrame();
    this._requestAnimationFrame(function() {
      var newpos = [
        self.currentCoord[0],
        self.currentCoord[1],
        self.currentCoord[2]
      ];
      if (firstPt && self.currentCoord[0]) {
        endPt = newpos;
        threeLinelengs = self.measureUtil.triangleLength(firstPt, newpos);
        //计算hPt
        if (firstPt[2] >= endPt[2]) {
          hPt = [endPt[0], endPt[1], firstPt[2]];
        } else {
          hPt = [firstPt[0], firstPt[1], endPt[2]];
        }
      }
    });
    this._clearEffect();
    this.scene.postProcessStages.fxaa.enabled = true;
    this._createHandler(
      function(click) {
        var ray = self.camera.getPickRay(click.position);
        var pos = self.globe.pick(ray, self.scene);
        var feature = self.scene.pick(click.position);
        if (feature) {
          if (feature.primitive instanceof Cesium.PointPrimitive) {
            return;
          }
        }
        if (pos || feature) {
          if (firstPt == null) {
            endPt = hPt = firstPt = [
              self.currentCoord[0],
              self.currentCoord[1],
              self.currentCoord[2]
            ];
            //绘制三角形三条边
            //1：斜边
            if (type != "h" && type != "v") {
              var slinepts = new Cesium.CallbackProperty(function() {
                // return JSON.parse(JSON.stringify(drawptArray));
                return Cesium.Cartesian3.fromDegreesArrayHeights(
                  [].concat.apply([], [firstPt, endPt])
                );
              }, false);
              self._drawPolyline(slinepts, config);
              //斜边长
              var _slength = new Cesium.CallbackProperty(function() {
                // return JSON.parse(JSON.stringify(drawptArray));
                return threeLinelengs[0] == 0 ? "" : threeLinelengs[0] + " 米";
              }, false);
              var _spos = new Cesium.CallbackProperty(function() {
                return Cesium.Cartesian3.fromDegrees(
                  (firstPt[0] + endPt[0]) / 2,
                  (firstPt[1] + endPt[1]) / 2,
                  (firstPt[2] + endPt[2]) / 2
                );
              }, false);
              //添加label
              self.measureUtil.triangleLabel(_spos, _slength);
            }

            var hlinepts = new Cesium.CallbackProperty(function() {
              // return JSON.parse(JSON.stringify(drawptArray));
              return Cesium.Cartesian3.fromDegreesArrayHeights(
                [].concat.apply([], [firstPt, hPt])
              );
            }, false);
            hlineentity = self._drawPolylineBydepthFail(hlinepts, config);
            if (type == "h" || typeof type == "undefined") {
              //边长
              var _hlength = new Cesium.CallbackProperty(function() {
                // return JSON.parse(JSON.stringify(drawptArray));
                return threeLinelengs[1] == 0 ? "" : threeLinelengs[1] + " 米";
              }, false);
              var _hpos = new Cesium.CallbackProperty(function() {
                var ll = 0;
                if (firstPt[2] <= endPt[2]) {
                  ll = Cesium.Cartesian3.fromDegrees(
                    (firstPt[0] + hPt[0]) / 2,
                    (firstPt[1] + hPt[1]) / 2,
                    (firstPt[2] + hPt[2]) / 2
                  );
                } else {
                  ll = Cesium.Cartesian3.fromDegrees(
                    (hPt[0] + endPt[0]) / 2,
                    (hPt[1] + endPt[1]) / 2,
                    (hPt[2] + endPt[2]) / 2
                  );
                }
                return ll;
              }, false);
              self.measureUtil.triangleLabel(_hpos, _hlength);
            }

            var vlinepts = new Cesium.CallbackProperty(function() {
              // return JSON.parse(JSON.stringify(drawptArray));
              return Cesium.Cartesian3.fromDegreesArrayHeights(
                [].concat.apply([], [hPt, endPt])
              );
            }, false);
            vlineentity = self._drawPolylineBydepthFail(vlinepts, config);
            //边长
            if (type == "v" || typeof type == "undefined") {
              var _vlength = new Cesium.CallbackProperty(function() {
                // return JSON.parse(JSON.stringify(drawptArray));
                return threeLinelengs[2] == 0 ? "" : threeLinelengs[2] + " 米";
              }, false);
              var _vpos = new Cesium.CallbackProperty(function() {
                var ll = 0;
                if (firstPt[2] >= endPt[2]) {
                  ll = Cesium.Cartesian3.fromDegrees(
                    (firstPt[0] + hPt[0]) / 2,
                    (firstPt[1] + hPt[1]) / 2,
                    (firstPt[2] + hPt[2]) / 2
                  );
                } else {
                  ll = Cesium.Cartesian3.fromDegrees(
                    (hPt[0] + endPt[0]) / 2,
                    (hPt[1] + endPt[1]) / 2,
                    (hPt[2] + endPt[2]) / 2
                  );
                }
                return ll;
              }, false);
              self.measureUtil.triangleLabel(_vpos, _vlength);
            }
          } else {
            var entities = self.viewer.entities;
            if (hlineentity) {
              entities.remove(hlineentity);
            }
            if (vlineentity) {
              entities.remove(vlineentity);
            }
            self._drawPolyline(
              Cesium.Cartesian3.fromDegreesArrayHeights(
                [].concat.apply([], [firstPt, hPt])
              ),
              config
            );
            self._drawPolyline(
              Cesium.Cartesian3.fromDegreesArrayHeights(
                [].concat.apply([], [hPt, endPt])
              ),
              config
            );

            self._clearEffect();
            self._closeRequestAnimationFrame();
          }
        }
      },
      function() {
        self.setDepthTestAgainstTerrain(false);
        self._clearEffect();
        self._closeRequestAnimationFrame();
        if (callback) {
          callback();
        }
      }
    );
  },
  _drawCircle: function(point, radius, config) {
    var config = config
      ? config
      : {
          name: "",
          color: "#ffa500"
        };
    var entity = this.viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(point[0], point[1], point[2]),
      ellipse: {
        semiMajorAxis: radius,
        semiMinorAxis: radius,
        material: Cesium.Color.fromCssColorString(config.color).withAlpha(0.5)
      }
    });
    this.drawEntities.push(entity);
    return entity;
  },
  //绘制圆形
  drawCircle: function(cfg) {
    //配置对象合并
    var config = {
      name: "",
      color: "#ffa500"
    };
    if (cfg) {
      Object.assign(config, cfg);
    }
    this.setDepthTestAgainstTerrain(true);
    var self = this;
    var firstPt = null; //中心点
    var distanceLength = 0; //两点距离，不带高程的
    this._closeRequestAnimationFrame();
    this._requestAnimationFrame(function() {
      var newpos = [self.currentCoord[0], self.currentCoord[1], 0];
      if (firstPt && self.currentCoord[0]) {
        distanceLength = self.measureUtil.distance(
          [firstPt[0], firstPt[1], 0],
          newpos
        );
      }
    });
    this._clearEffect();
    this.scene.postProcessStages.fxaa.enabled = true;
    this._createHandler(
      function(click) {
        var ray = self.camera.getPickRay(click.position);
        var pos = self.globe.pick(ray, self.scene);
        var feature = self.scene.pick(click.position);
        if (feature) {
          if (feature.primitive instanceof Cesium.PointPrimitive) {
            return;
          }
        }
        if (pos || feature) {
          if (firstPt == null) {
            firstPt = [
              self.currentCoord[0],
              self.currentCoord[1],
              self.currentCoord[2]
            ];
            //圆半径
            var ratio = new Cesium.CallbackProperty(function() {
              // return JSON.parse(JSON.stringify(drawptArray));
              return distanceLength;
            }, false);
            self._drawCircle(firstPt, ratio, config);
          } else {
            self._clearEffect();
            self._closeRequestAnimationFrame();
          }
        }
      },
      function() {
        self.setDepthTestAgainstTerrain(false);
        self._clearEffect();
        self._closeRequestAnimationFrame();
      }
    );
  },

  _drawEllipse: function(point, radius, radius2, config) {
    var config = config
      ? config
      : {
          name: "",
          color: "#ffa500"
        };
    var entity = this.viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(point[0], point[1], point[2]),
      ellipse: {
        semiMajorAxis: radius,
        semiMinorAxis: radius2,
        material: Cesium.Color.fromCssColorString(config.color).withAlpha(0.5)
      }
    });
    this.drawEntities.push(entity);
    return entity;
  },
  //绘制椭圆
  drawEllipse: function(cfg) {
    //配置对象合并
    var config = {
      name: "",
      color: "#ffa500"
    };
    if (cfg) {
      Object.assign(config, cfg);
    }
    this.setDepthTestAgainstTerrain(true);
    var self = this;
    var firstPt = null; //中心点
    var distanceLength = 0; //两点距离，不带高程的
    this._closeRequestAnimationFrame();
    this._requestAnimationFrame(function() {
      var newpos = [self.currentCoord[0], self.currentCoord[1], 0];
      if (firstPt && self.currentCoord[0]) {
        distanceLength = self.measureUtil.distance(
          [firstPt[0], firstPt[1], 0],
          newpos
        );
      }
    });
    this._clearEffect();
    this.scene.postProcessStages.fxaa.enabled = true;
    this._createHandler(
      function(click) {
        var ray = self.camera.getPickRay(click.position);
        var pos = self.globe.pick(ray, self.scene);
        var feature = self.scene.pick(click.position);
        if (feature) {
          if (feature.primitive instanceof Cesium.PointPrimitive) {
            return;
          }
        }
        if (pos || feature) {
          if (firstPt == null) {
            firstPt = [
              self.currentCoord[0],
              self.currentCoord[1],
              self.currentCoord[2]
            ];
            //长半轴
            var ratio = new Cesium.CallbackProperty(function() {
              // return JSON.parse(JSON.stringify(drawptArray));
              return distanceLength;
            }, false);
            //短半轴
            var ratio2 = new Cesium.CallbackProperty(function() {
              // return JSON.parse(JSON.stringify(drawptArray));
              return distanceLength / 2;
            }, false);
            self._drawEllipse(firstPt, ratio, ratio2, config);
          } else {
            self._clearEffect();
            self._closeRequestAnimationFrame();
          }
        }
      },
      function() {
        self.setDepthTestAgainstTerrain(false);
        self._clearEffect();
        self._closeRequestAnimationFrame();
      }
    );
  },
  _drawRectangle: function(rectangle, config) {
    var config = config
      ? config
      : {
          name: "",
          color: "#ffa500"
        };
    var entity = this.viewer.entities.add({
      rectangle: {
        coordinates: rectangle,
        material: Cesium.Color.fromCssColorString(config.color).withAlpha(0.5)
      }
    });
    this.drawEntities.push(entity);
    return entity;
  },
  //绘制矩形
  drawRectangle: function(cfg) {
    //配置对象合并
    var config = {
      name: "",
      color: "#ffa500"
    };
    if (cfg) {
      Object.assign(config, cfg);
    }
    this.setDepthTestAgainstTerrain(true);
    var self = this;
    var startPt = null, //起点
      endPt = null; //终点
    this._closeRequestAnimationFrame();
    this._requestAnimationFrame(function() {
      var newpos = [self.currentCoord[0], self.currentCoord[1], 0];
      if (startPt && self.currentCoord[0]) {
        endPt = newpos;
      }
    });
    this._clearEffect();
    this.scene.postProcessStages.fxaa.enabled = true;
    this._createHandler(
      function(click) {
        var ray = self.camera.getPickRay(click.position);
        var pos = self.globe.pick(ray, self.scene);
        var feature = self.scene.pick(click.position);
        if (feature) {
          if (feature.primitive instanceof Cesium.PointPrimitive) {
            return;
          }
        }
        if (pos || feature) {
          if (startPt == null) {
            endPt = startPt = [self.currentCoord[0], self.currentCoord[1]];
            //圆半径
            var rect = new Cesium.CallbackProperty(function() {
              return Cesium.Rectangle.fromDegrees(
                Math.min(startPt[0], endPt[0]),
                Math.min(startPt[1], endPt[1]),
                Math.max(startPt[0], endPt[0]),
                Math.max(startPt[1], endPt[1])
              );
            }, false);
            self._drawRectangle(rect, config);
          } else {
            self._clearEffect();
            self._closeRequestAnimationFrame();
          }
        }
      },
      function() {
        self.setDepthTestAgainstTerrain(false);
        self._clearEffect();
        self._closeRequestAnimationFrame();
      }
    );
  }
};
export { CesiumDrawHelper };
/***
 *空间测量工具类（面积、长度计算，label显示等）
 ***/
var CesiumMeasureUtil = function(viewer) {
  this.earthRadiusMeters = 6371000.0;
  this.radiansPerDegree = Math.PI / 180.0;
  this.degreesPerRadian = 180.0 / Math.PI;
  this.viewer = viewer;
  this.drawEntities = [];
  this.trianglePolygons = []; //三角格网
  this._init();
};
CesiumMeasureUtil.prototype = {
  constructor: CesiumMeasureUtil,
  _init: function() {},
  clear: function() {
    var entities = this.viewer.entities;
    for (var i = 0; i < this.drawEntities.length; i++) {
      entities.remove(this.drawEntities[i]);
    }
    for (var i = 0; i < this.trianglePolygons.length; i++) {
      viewer.dataSources.remove(this.trianglePolygons[i]);
    }
    this.drawEntities = [];
  },
  //直线的总长度label
  totalLengthLabel: function(point, len) {
    var entity = this.viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(point[0], point[1], point[2]),
      label: {
        text: len,
        font: "30px 楷体",
        scale: 0.5,
        showBackground: true,
        backgroundColor: Cesium.Color.fromCssColorString("rgba(0,0,0,0.6)"),
        backgroundPadding: new Cesium.Cartesian2(10, 8),
        fillColor: Cesium.Color.WHITE,
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        outlineWidth: 2,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        pixelOffset: new Cesium.Cartesian2(20, -20),
        disableDepthTestDistance: 0
      }
    });
    this.drawEntities.push(entity);
  },
  //每段线的长度label
  segmentLabel: function(point1, point2, distance) {
    var entity = this.viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(point1[0], point1[1], point1[2]),
      label: {
        text: distance.toFixed(1) + "米",
        font: "30px 楷体",
        scale: 0.5,
        showBackground: true,
        backgroundColor: Cesium.Color.fromCssColorString("rgba(0,0,0,0.6)"),
        backgroundPadding: new Cesium.Cartesian2(10, 8),
        fillColor: Cesium.Color.WHITE,
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        outlineWidth: 2,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        pixelOffset: new Cesium.Cartesian2(20, -20),
        // disableDepthTestDistance: Number.POSITIVE_INFINITY
        disableDepthTestDistance: 0
      }
    });
    this.drawEntities.push(entity);
  },
  //面积label
  areaLabel: function(point, area) {
    var entity = this.viewer.entities.add({
      position: point,
      label: {
        text: area,
        font: "30px 楷体",
        scale: 0.5,
        showBackground: true,
        backgroundColor: Cesium.Color.fromCssColorString("rgba(0,0,0,0.6)"),
        backgroundPadding: new Cesium.Cartesian2(10, 8),
        fillColor: Cesium.Color.WHITE,
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        outlineWidth: 2,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        pixelOffset: new Cesium.Cartesian2(20, -20),
        // disableDepthTestDistance: Number.POSITIVE_INFINITY
        disableDepthTestDistance: 0
      }
    });
    this.drawEntities.push(entity);
  },
  //空间测量时，三角形边长label
  triangleLabel: function(pos, distance) {
    var entity = this.viewer.entities.add({
      position: pos,
      label: {
        text: distance,
        font: "30px 楷体",
        scale: 0.5,
        showBackground: true,
        backgroundColor: Cesium.Color.fromCssColorString("rgba(0,0,0,0.6)"),
        backgroundPadding: new Cesium.Cartesian2(10, 8),
        fillColor: Cesium.Color.WHITE,
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        outlineWidth: 2,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        // pixelOffset: new Cesium.Cartesian2(20, -20),
        disableDepthTestDistance: Number.POSITIVE_INFINITY
        // disableDepthTestDistance: 0,
      }
    });
    this.drawEntities.push(entity);
  },
  //计算两点间距离（空间直线距离）
  getFlatternDistance: function(lat1, lng1, height1, lat2, lng2, height2) {
    var EARTH_RADIUS = 6378137.0; //单位M
    var PI = Math.PI;
    function getRad(d) {
      return (d * PI) / 180.0;
    }
    var f = getRad((lat1 + lat2) / 2);
    var g = getRad((lat1 - lat2) / 2);
    var l = getRad((lng1 - lng2) / 2);
    var sg = Math.sin(g);
    var sl = Math.sin(l);
    var sf = Math.sin(f);
    var s, c, w, r, d, h1, h2;
    var a = EARTH_RADIUS;
    var fl = 1 / 298.257;
    sg = sg * sg;
    sl = sl * sl;
    sf = sf * sf;
    s = sg * (1 - sl) + (1 - sf) * sl;
    c = (1 - sg) * (1 - sl) + sf * sl;
    w = Math.atan(Math.sqrt(s / c));
    r = Math.sqrt(s * c) / w;
    d = 2 * w * a;
    h1 = (3 * r - 1) / 2 / c;
    h2 = (3 * r + 1) / 2 / s;
    var sp_dis = d * (1 + fl * (h1 * sf * (1 - sg) - h2 * (1 - sf) * sg));
    var real_dis = Math.sqrt(
      Math.pow(sp_dis, 2) + Math.pow(height1 - height2, 2)
    );
    real_dis = real_dis ? real_dis : 0;
    return real_dis;
  },
  //计算两点间距离（贴地距离）
  getFollowDistance: function(lat1, lng1, lat2, lng2) {
    //两点之前取样点个数
    var sampleCount = 100;
    var steplng = (lng1 - lng2) / sampleCount;
    var steplat = (lat1 - lat2) / sampleCount;
    var pts = [];
    var distance = 0;
    for (var j = 0; j <= sampleCount; j++) {
      var calclng = lng1 - j * steplng;
      var calclat = lat1 - j * steplat;
      var carto = new Cesium.Cartographic.fromDegrees(calclng, calclat);
      var h1 = viewer.scene.globe.getHeight(carto);
      h1 = h1 ? h1 : 0;
      // console.log([calclng,calclat,h1]);
      pts.push([calclng, calclat, h1]);
      if (j >= 1) {
        var segdis = this.getFlatternDistance(
          calclat,
          calclng,
          h1,
          pts[j - 1][1],
          pts[j - 1][0],
          pts[j - 1][2]
        );
        distance += segdis;
      }
    }
    return distance;
  },
  //计算多边形面积（空间面积）
  SphericalPolygonAreaMeters: function(points) {
    if (
      points[2][0] == points[1][0] &&
      points[2][1] == points[1][1] &&
      points[2][2] == points[1][2]
    ) {
      return 0;
    }
    var res = 0;
    for (var i = 0; i < points.length - 2; i++) {
      var j = (i + 1) % points.length;
      var k = (i + 2) % points.length;
      totalAngle = this.Angle(points[j], points[0], points[k]);
      // console.log(totalAngle+'----------'+i);
      var dis_temp1 = this.distance(points[j], points[0]);
      var dis_temp2 = this.distance(points[k], points[0]);
      var singlearea = (dis_temp1 * dis_temp2 * Math.sin(totalAngle)) / 2;
      singlearea = singlearea ? singlearea : 0;
      // console.log(singlearea+'----------'+i);
      res += Math.abs(singlearea);
    }
    return Math.abs(res.toFixed(4));
  },
  //计算多边形面积（投影面积）
  TyPolygonAreaMeters: function(points) {
    if (
      points[2][0] == points[1][0] &&
      points[2][1] == points[1][1] &&
      points[2][2] == points[1][2]
    ) {
      return 0;
    }
    var res = 0;
    for (var i = 0; i < points.length - 2; i++) {
      var j = (i + 1) % points.length;
      var k = (i + 2) % points.length;
      totalAngle = this.Angle(points[j], points[0], points[k]);
      // console.log(totalAngle+'----------'+i);
      var dis_temp1 = this.distancePlane(points[j], points[0]);
      var dis_temp2 = this.distancePlane(points[k], points[0]);
      var singlearea = (dis_temp1 * dis_temp2 * Math.sin(totalAngle)) / 2;
      // console.log(singlearea+'----------'+i);
      res += Math.abs(singlearea);
    }
    return Math.abs(res.toFixed(4));
  },
  //计算多边形面积（贴地面积）
  TdPolygonAreaMeters: function(points) {
    var self = this;
    var cellCount = 80; //bbox分成多少个小正方格
    var len = points.length - 1;
    points.push(points[0]);
    var turfline = turf.lineString(points);
    var polygon = turf.polygon([points], { name: "面" });
    var bbox = turf.bbox(polygon); //[minx,miny,maxx,maxy]
    // console.log(bbox);
    //计算包围盒的长宽，用来计算每个小方格长度是多少
    var width = this.getFlatternDistance(
      bbox[1],
      bbox[0],
      0,
      bbox[1],
      bbox[2],
      0
    ); //东西走向
    var height = this.getFlatternDistance(
      bbox[1],
      bbox[0],
      0,
      bbox[3],
      bbox[0],
      0
    ); //南北走向
    // console.log(width,height);
    // var bboxPolygon = turf.bboxPolygon(bbox);
    var cellSide =
      height / Math.sqrt(cellCount / (width / (width + height))) / 1000;
    // console.log(width,height,cellSide);
    var options = { units: "kilometers" };
    var grid = turf.pointGrid(bbox, cellSide, options);
    var features = grid.features;
    var resultpts = [];
    for (var i = 0; i < features.length; i++) {
      if (turf.booleanPointInPolygon(features[i], polygon)) {
        var gridpt = features[i].geometry.coordinates;
        var carto = new Cesium.Cartographic.fromDegrees(gridpt[0], gridpt[1]);
        var h1 = viewer.scene.globe.getHeight(carto);
        h1 = h1 ? h1 : 0;
        gridpt.push(h1);
        var turfpt = turf.point(gridpt);
        if (
          turf.nearestPointOnLine(turfline, turfpt, { units: "kilometers" })
            .properties.dist >=
          cellSide * 0.8
        ) {
          resultpts.push(turfpt);
          var entity = this.viewer.entities.add({
            name: "",
            position: Cesium.Cartesian3.fromDegrees(gridpt[0], gridpt[1], h1),
            point: {
              color: Cesium.Color.fromCssColorString("red"),
              pixelSize: 10,
              disableDepthTestDistance: Number.POSITIVE_INFINITY
              // heightReference:Cesium.HeightReference.NONE
            }
          });
          this.drawEntities.push(entity);
        }
      }
    }
    //每条边线也等距插入一些点
    for (var s = 0; s < points.length - 1; s++) {
      var startpt = points[s];
      var nextpt = points[s + 1];
      var seglength = this.getFlatternDistance(
        startpt[1],
        startpt[0],
        0,
        nextpt[1],
        nextpt[0],
        0
      ); //东西走向
      //分割的份数
      var splitcount = Math.floor(seglength / (cellSide * 1000));
      // console.log(splitcount);
      var steplng = (startpt[0] - nextpt[0]) / splitcount;
      var steplat = (startpt[1] - nextpt[1]) / splitcount;
      for (var j = 0; j < splitcount; j++) {
        var calclng = startpt[0] - j * steplng;
        var calclat = startpt[1] - j * steplat;
        var carto = new Cesium.Cartographic.fromDegrees(calclng, calclat);
        var h1 = viewer.scene.globe.getHeight(carto);
        h1 = h1 ? h1 : 0;
        resultpts.push(turf.point([calclng, calclat, h1]));
        var entity = this.viewer.entities.add({
          name: "",
          position: Cesium.Cartesian3.fromDegrees(calclng, calclat, h1),
          point: {
            color: Cesium.Color.fromCssColorString("red"),
            pixelSize: 10,
            disableDepthTestDistance: Number.POSITIVE_INFINITY
            // heightReference:Cesium.HeightReference.NONE
          }
        });
        this.drawEntities.push(entity);
      }
    }
    //连接三角网
    var tin = turf.tin(turf.featureCollection(resultpts));
    //计算每个三角形面积，累计求和
    // console.log(tin);
    var trigfeatures = tin.features;
    var sumarea = 0;
    for (var k = 0; k < trigfeatures.length; k++) {
      var fea = trigfeatures[k];
      var pts = fea.geometry.coordinates[0];
      sumarea += this.SphericalPolygonAreaMeters(pts);
    }
    // console.log(sumarea);
    var promise = Cesium.GeoJsonDataSource.load(tin);
    promise.then(function(dataSource) {
      this.viewer.dataSources.add(dataSource).then(function(dt) {
        self.trianglePolygons.push(dt);
      });
      var entities = dataSource.entities.values;
      for (var i = 0; i < entities.length; i++) {
        var entity = entities[i];
        // this.drawEntities.push(entity);
        entity.myid = i;
        var color = Cesium.Color.fromCssColorString("rgba(0,0,0,0)");
        // if (!color) {
        //  //创建随机色
        //     color =Cesium.Color.fromRandom({
        //         alpha: 1.0
        //     });
        // }

        entity.polygon.material = color;
        entity.polygon.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND;
        // entity.polygon.outline = false;
        entity.polygon.outlineColor = Cesium.Color.WHITE;
        entity.polygon.outlineWidth = 2;
        // entity.polygon.extrudedHeight =1000.0;
      }
    });
    return sumarea;
  },
  /*角度*/
  Angle: function(p1, p2, p3) {
    var bearing21 = this.Bearing(p2, p1);
    var bearing23 = this.Bearing(p2, p3);
    var angle = bearing21 - bearing23;
    if (angle < 0) {
      angle += 360;
    }
    return angle;
  },
  /*方向*/
  Bearing: function(from, to) {
    var lat1 = from[1] * this.radiansPerDegree;
    var lon1 = from[0] * this.radiansPerDegree;
    var lat2 = to[1] * this.radiansPerDegree;
    var lon2 = to[0] * this.radiansPerDegree;
    var angle = -Math.atan2(
      Math.sin(lon1 - lon2) * Math.cos(lat2),
      Math.cos(lat1) * Math.sin(lat2) -
        Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2)
    );
    if (angle < 0) {
      angle += Math.PI * 2.0;
    }
    angle = angle * this.degreesPerRadian;
    return angle;
  },
  /*两个经纬度距离-带高度计算*/
  distance: function(point1, point2) {
    var point1cartographic = Cesium.Cartographic.fromDegrees(
      point1[0],
      point1[1],
      point1[2]
    );
    var point2cartographic = Cesium.Cartographic.fromDegrees(
      point2[0],
      point2[1],
      point2[2]
    );
    /**根据经纬度计算出距离**/
    var geodesic = new Cesium.EllipsoidGeodesic();
    geodesic.setEndPoints(point1cartographic, point2cartographic);
    var s = geodesic.surfaceDistance;
    //返回两点之间的距离
    s = Math.sqrt(
      Math.pow(s, 2) +
        Math.pow(point2cartographic.height - point1cartographic.height, 2)
    );
    return s;
  },
  /*两个经纬度球面距离--不带高度计算*/
  distancePlane: function(point1, point2) {
    var point1cartographic = Cesium.Cartographic.fromDegrees(
      point1[0],
      point1[1],
      point1[2]
    );
    var point2cartographic = Cesium.Cartographic.fromDegrees(
      point2[0],
      point2[1],
      point2[2]
    );
    /**根据经纬度计算出距离**/
    var geodesic = new Cesium.EllipsoidGeodesic();
    geodesic.setEndPoints(point1cartographic, point2cartographic);
    var s = geodesic.surfaceDistance;
    return s;
  },
  /*两个经纬度组成的三角形三条边长，数组格式：[斜边、垂直边、水平边]*/
  triangleLength: function(point1, point2) {
    var point1cartographic = Cesium.Cartographic.fromDegrees(
      point1[0],
      point1[1],
      point1[2]
    );
    var point2cartographic = Cesium.Cartographic.fromDegrees(
      point2[0],
      point2[1],
      point2[2]
    );
    /**根据经纬度计算出距离**/
    var geodesic = new Cesium.EllipsoidGeodesic();
    geodesic.setEndPoints(point1cartographic, point2cartographic);
    var s = geodesic.surfaceDistance.toFixed(2); //斜边长
    var h = Math.abs(
      point2cartographic.height - point1cartographic.height
    ).toFixed(2);
    var v = Math.sqrt(
      Math.pow(s, 2) -
        Math.pow(point2cartographic.height - point1cartographic.height, 2)
    ).toFixed(2);
    return [s, h, v];
  }
};
export { CesiumMeasureUtil };
